package com.bsg.upm.check;

import java.text.MessageFormat;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.springframework.stereotype.Service;

import com.bsg.upm.constant.Messages;
import com.bsg.upm.entity.ClusterEntity;
import com.bsg.upm.entity.NetworkingEntity;
import com.bsg.upm.entity.SiteEntity;
import com.bsg.upm.exception.APIException;
import com.bsg.upm.util.IpV4Utils;

/**
 * 网段业务处理检查
 * 
 * @author HCK
 *
 */
@Service
public class NetworkingCheck extends BaseCheck {

	/**
	 * 网段新增时检查
	 * 
	 * @param paramMap
	 *            请求参数
	 * @return CheckResult检查结果对象
	 */
	public CheckResult checkSave(Map<String, Object> paramMap) {
		// 非逻辑检查
		CheckResult chkRS = checkSaveNonLogic(paramMap);
		if (chkRS.isError()) {
			return chkRS;
		}

		// 逻辑检查
		chkRS = checkSaveLogic(paramMap);
		if (chkRS.isError()) {
			return chkRS;
		}
		return chkRS;
	}

	/**
	 * 网段编辑时检查
	 * 
	 * @param paramMap
	 *            请求参数
	 * @return CheckResult检查结果对象
	 * @throws APIException
	 *             API异常处理类
	 */
	public CheckResult checkUpdate(Map<String, Object> paramMap) throws APIException {
		// 非逻辑检查
		CheckResult chkRS = checkUpdateNonLogic(paramMap);
		if (chkRS.isError()) {
			return chkRS;
		}

		// 逻辑检查
		chkRS = checkUpdateLogic(paramMap);
		if (chkRS.isError()) {
			return chkRS;
		}
		return chkRS;
	}

	/**
	 * 网段启用时检查
	 * 
	 * @param networking
	 *            网段对象
	 * @return CheckResult检查结果对象
	 */
	public CheckResult checkEnable(NetworkingEntity networking) {
		CheckResult chkRS = new CheckResult();
		// 存在性检查
		if (networking == null) {
			chkRS.setStatus(HttpStatus.SC_GONE);
			chkRS.setErrorMsg(MessageFormat.format(Messages.NOT_EXIST, "网段"));
			return chkRS;
		}

		// 网段状态检查
		if (networking.getEnabled()) {
			chkRS.setStatus(HttpStatus.SC_CONFLICT);
			chkRS.setErrorMsg(Messages.ENABLED_ALREADY);
			return chkRS;
		}
		return chkRS;
	}

	/**
	 * 网段停用时检查
	 * 
	 * @param networking
	 *            网段对象
	 * @return CheckResult检查结果对象
	 */
	public CheckResult checkDisable(NetworkingEntity networking) {
		CheckResult chkRS = new CheckResult();
		// 存在性检查
		if (networking == null) {
			chkRS.setStatus(HttpStatus.SC_GONE);
			chkRS.setErrorMsg(MessageFormat.format(Messages.NOT_EXIST, "网段"));
			return chkRS;
		}

		// 网段状态检查
		if (!networking.getEnabled()) {
			chkRS.setStatus(HttpStatus.SC_GONE);
			chkRS.setErrorMsg(Messages.DISABLED_ALREADY);
			return chkRS;
		}
		return chkRS;
	}

	/**
	 * 网段删除时检查
	 * 
	 * @param networking
	 *            区域对象
	 * @return CheckResult检查结果对象
	 */
	public CheckResult checkRemove(NetworkingEntity networking) throws APIException {
		CheckResult chkRS = new CheckResult();
		// 存在性检查
		if (networking == null) {
			chkRS.setStatus(HttpStatus.SC_GONE);
			chkRS.setErrorMsg(MessageFormat.format(Messages.NOT_EXIST, "网段"));
			return chkRS;
		}

		// 网段状态检查
		if (networking.getEnabled()) {
			chkRS.setStatus(HttpStatus.SC_CONFLICT);
			chkRS.setErrorMsg(MessageFormat.format(Messages.ENABLED_NOT_DELETE, "网段"));
			return chkRS;
		}

		ClusterEntity cluster = networking.getCluster();
		// 网段关联资源检查
		if (cluster != null && StringUtils.isNotBlank(cluster.getId())) {
			chkRS.setStatus(HttpStatus.SC_CONFLICT);
			chkRS.setErrorMsg("该网段已关联集群，无法删除");
			return chkRS;
		}

		return chkRS;
	}

	/**
	 * 新增时非业务逻辑(非空和长度)检查
	 * 
	 * @param paramMap
	 *            请求参数
	 * @return CheckResult检查结果对象
	 */
	private CheckResult checkSaveNonLogic(Map<String, Object> paramMap) {
		CheckResult chkRS = new CheckResult();
		// 站点非空检查
		String siteId = (String) paramMap.get("site");
		if (StringUtils.isBlank(siteId)) {
			chkRS.setStatus(HttpStatus.SC_BAD_REQUEST);
			chkRS.setErrorMsg(MessageFormat.format(Messages.NULL_NOT_ALLOWED, "所属站点"));
			return chkRS;
		}

		// 网段名称非空和长度检查
		String name = (String) paramMap.get("name");
		if (StringUtils.isBlank(name)) {
			chkRS.setStatus(HttpStatus.SC_BAD_REQUEST);
			chkRS.setErrorMsg(MessageFormat.format(Messages.NULL_NOT_ALLOWED, "网段名称"));
			return chkRS;
		}
		if (StringUtils.trim(name).length() > 64) {
			chkRS.setStatus(HttpStatus.SC_BAD_REQUEST);
			chkRS.setErrorMsg(MessageFormat.format(Messages.MAXLENGTH_NOT_ALLOWED, "网段名称", 64));
			return chkRS;
		}

		// 起始IP非空和有效性检查
		String startIp = (String) paramMap.get("startIp");
		if (StringUtils.isBlank(startIp)) {
			chkRS.setStatus(HttpStatus.SC_BAD_REQUEST);
			chkRS.setErrorMsg(MessageFormat.format(Messages.NULL_NOT_ALLOWED, "起始IP"));
			return chkRS;
		}
		if (!IpV4Utils.ipV4Validate(startIp)) {
			chkRS.setStatus(HttpStatus.SC_BAD_REQUEST);
			chkRS.setErrorMsg(MessageFormat.format(Messages.FORMAT_NOT_ALLOWED, "起始IP"));
			return chkRS;
		}

		// 结束IP非空和有效性检查
		String endIp = (String) paramMap.get("endIp");
		if (StringUtils.isBlank(endIp)) {
			chkRS.setStatus(HttpStatus.SC_BAD_REQUEST);
			chkRS.setErrorMsg(MessageFormat.format(Messages.NULL_NOT_ALLOWED, "结束IP"));
			return chkRS;
		}
		if (!IpV4Utils.ipV4Validate(endIp)) {
			chkRS.setStatus(HttpStatus.SC_BAD_REQUEST);
			chkRS.setErrorMsg(MessageFormat.format(Messages.FORMAT_NOT_ALLOWED, "结束IP"));
			return chkRS;
		}

		// 网关非空和有效性检查
		String gateway = (String) paramMap.get("gateway");
		if (StringUtils.isBlank(gateway)) {
			chkRS.setStatus(HttpStatus.SC_BAD_REQUEST);
			chkRS.setErrorMsg(MessageFormat.format(Messages.NULL_NOT_ALLOWED, "网关"));
			return chkRS;
		}
		if (!IpV4Utils.ipV4Validate(gateway)) {
			chkRS.setStatus(HttpStatus.SC_BAD_REQUEST);
			chkRS.setErrorMsg(MessageFormat.format(Messages.FORMAT_NOT_ALLOWED, "网关"));
			return chkRS;
		}

		// 掩码非空和有效性检查
		Integer prefix = (Integer) paramMap.get("prefix");
		if (prefix == null) {
			chkRS.setStatus(HttpStatus.SC_BAD_REQUEST);
			chkRS.setErrorMsg(MessageFormat.format(Messages.NULL_NOT_ALLOWED, "掩码"));
			return chkRS;
		}
		if (prefix < 0 || prefix > 255) {
			chkRS.setStatus(HttpStatus.SC_BAD_REQUEST);
			chkRS.setErrorMsg(MessageFormat.format(Messages.BETWEEN_MIN_AND_MAX, "VLAN ID", 0, 255));
			return chkRS;
		}

		// VLAN ID非空和有效性检查
		Integer vlanId = (Integer) paramMap.get("vlanId");
		if (vlanId == null) {
			chkRS.setStatus(HttpStatus.SC_BAD_REQUEST);
			chkRS.setErrorMsg(MessageFormat.format(Messages.NULL_NOT_ALLOWED, "VLAN ID"));
			return chkRS;
		}
		if (vlanId < 0 || vlanId > 10240) {
			chkRS.setStatus(HttpStatus.SC_BAD_REQUEST);
			chkRS.setErrorMsg(MessageFormat.format(Messages.BETWEEN_MIN_AND_MAX, "VLAN ID", 0, 10240));
			return chkRS;
		}

		if (paramMap.containsKey("description")) {
			// 描述长度检查
			String description = (String) paramMap.get("description");
			if (StringUtils.trim(description).length() > 256) {
				chkRS.setStatus(HttpStatus.SC_BAD_REQUEST);
				chkRS.setErrorMsg(MessageFormat.format(Messages.MAXLENGTH_NOT_ALLOWED, "描述", 256));
				return chkRS;
			}
		}

		return chkRS;
	}

	/**
	 * 新增时业务逻辑检查
	 * 
	 * @param paramMap
	 *            请求参数
	 * @return CheckResult检查结果对象
	 */
	private CheckResult checkSaveLogic(Map<String, Object> paramMap) {
		CheckResult chkRS = new CheckResult();
		// 站点存在性检查
		String siteId = (String) paramMap.get("site");
		SiteEntity site = siteDao.get(siteId);
		if (site == null) {
			chkRS.setStatus(HttpStatus.SC_GONE);
			chkRS.setErrorMsg(MessageFormat.format(Messages.NOT_EXIST, "所属站点"));
			return chkRS;
		}

		// 网段名称重复性检查
		String name = (String) paramMap.get("name");
		if (networkingDao.countBySiteIdAndName(siteId, name) > 0) {
			chkRS.setStatus(HttpStatus.SC_CONFLICT);
			chkRS.setErrorMsg(MessageFormat.format(Messages.EXIST, "站点下网段名称"));
			return chkRS;
		}

		// 起始IP和结束IP必须在同一网段内
		String startIp = (String) paramMap.get("startIp");
		String endIp = (String) paramMap.get("endIp");
		if (!IpV4Utils.checkSameSegmentByDefault(startIp, endIp)) {
			chkRS.setStatus(HttpStatus.SC_BAD_REQUEST);
			chkRS.setErrorMsg("起始IP和结束IP必须在同一个网段内");
			return chkRS;
		}
		if (IpV4Utils.compareIpV4s(startIp, endIp) != -1) {
			chkRS.setStatus(HttpStatus.SC_BAD_REQUEST);
			chkRS.setErrorMsg("结束IP必须大于起始IP");
			return chkRS;
		}

		// IP地址和网关必须在同一网段内
		String gateway = (String) paramMap.get("gateway");
		if (!IpV4Utils.checkSameSegmentByDefault(startIp, gateway)) {
			chkRS.setStatus(HttpStatus.SC_BAD_REQUEST);
			chkRS.setErrorMsg("IP地址和网关必须在同一个网段内");
			return chkRS;
		}

		// IP段重复性检查
		List<NetworkingEntity> networkings = networkingDao.listStartAndEndIpBySiteId(siteId);
		for (NetworkingEntity n : networkings) {
			if (!IpV4Utils.checkSameSegmentByDefault(startIp, n.getStartIp())) {
				if (!(Integer.parseInt(endIp.split("\\.")[3]) <= Integer.parseInt(n.getStartIp().split("\\.")[3])
						|| Integer.parseInt(startIp.split("\\.")[3]) >= Integer
								.parseInt(n.getEndIp().split("\\.")[3]))) {
					chkRS.setStatus(HttpStatus.SC_CONFLICT);
					chkRS.setErrorMsg("该站点下IP地址已存在");
					return chkRS;
				}
			}
		}
		return chkRS;
	}

	/**
	 * 编辑时非业务逻辑(非空和长度)检查
	 * 
	 * @param paramMap
	 *            请求参数
	 * @return CheckResult检查结果对象
	 */
	private CheckResult checkUpdateNonLogic(Map<String, Object> paramMap) {
		CheckResult chkRS = new CheckResult();
		// 网段非空检查
		String networkingId = (String) paramMap.get("networkingId");
		if (StringUtils.isBlank(networkingId)) {
			chkRS.setStatus(HttpStatus.SC_BAD_REQUEST);
			chkRS.setErrorMsg(MessageFormat.format(Messages.NULL_NOT_ALLOWED, "网段编码"));
			return chkRS;
		}

		if (paramMap.containsKey("name")) {
			// 网段名称非空和长度检查
			String name = (String) paramMap.get("name");
			if (StringUtils.isBlank(name)) {
				chkRS.setStatus(HttpStatus.SC_BAD_REQUEST);
				chkRS.setErrorMsg(MessageFormat.format(Messages.NULL_NOT_ALLOWED, "网段名称"));
				return chkRS;
			}
			if (StringUtils.trim(name).length() > 64) {
				chkRS.setStatus(HttpStatus.SC_BAD_REQUEST);
				chkRS.setErrorMsg(MessageFormat.format(Messages.MAXLENGTH_NOT_ALLOWED, "网段名称", 64));
				return chkRS;
			}
		}

		if (paramMap.containsKey("description")) {
			// 描述长度检查
			String description = (String) paramMap.get("description");
			if (StringUtils.trim(description).length() > 256) {
				chkRS.setStatus(HttpStatus.SC_BAD_REQUEST);
				chkRS.setErrorMsg(MessageFormat.format(Messages.MAXLENGTH_NOT_ALLOWED, "描述", 256));
				return chkRS;
			}
		}

		return chkRS;
	}

	/**
	 * 编辑时业务逻辑检查
	 * 
	 * @param paramMap
	 *            请求参数
	 * @return CheckResult检查结果对象
	 */
	private CheckResult checkUpdateLogic(Map<String, Object> paramMap) throws APIException {
		CheckResult chkRS = new CheckResult();
		String networkingId = (String) paramMap.get("networkingId");

		// 网段存在性检查
		NetworkingEntity networking = networkingDao.get(networkingId);
		if (networking == null) {
			chkRS.setStatus(HttpStatus.SC_GONE);
			chkRS.setErrorMsg(MessageFormat.format(Messages.NOT_EXIST, "网段"));
			return chkRS;
		}

		// 网段状态检查
		if (networking.getEnabled()) {
			chkRS.setStatus(HttpStatus.SC_CONFLICT);
			chkRS.setErrorMsg(MessageFormat.format(Messages.ENABLED_NOT_UPDATE, "网段"));
			return chkRS;
		}

		if (paramMap.containsKey("name")) {
			// 网段名称重复性检查
			String name = (String) paramMap.get("name");
			if (!name.equals(networking.getName())) {
				if (networkingDao.countBySiteIdAndName(networking.getSite().getId(), name) > 0) {
					chkRS.setStatus(HttpStatus.SC_CONFLICT);
					chkRS.setErrorMsg(MessageFormat.format(Messages.EXIST, "站点下网段名称"));
					return chkRS;
				}
			}
		}

		return chkRS;
	}
}
